<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Array的变化侦测</title>
</head>

<body>
  <p>数组的变化侦测与对象的变化侦测不一样。他是通过方法来改变内容的，我们创建拦截器覆盖原型方式来追踪变化。</p>
  <p>为了不污染全局的Array.prototype，我们在Observer中只针对那些需要侦测变化的数组使用__proto__来覆盖原型方法。</p>
  <p>Array收集依赖的方式也是在getter中进行，由于使用依赖不同，数组要在拦截器中向依赖发消息。所以要把依赖保存在Observer实例中</p>
  <p>在Observer中，我们对每个侦测了变化的数据都标记上__ob__，并且把this保存在__ob__上。一方面可以标记数据是否被侦测了变化，另一方面可以方便通过数据获取__ob__。从而拿到Observer实例上保存的依赖
    。当拦截发生变化，向依赖发送通知。</p>
  <script src="./index.js"></script>

  <script>
    const arrayProto = Array.prototype
    const arrayMethods = Object.create(arrayProto);
    ['push', 'pop', 'shift', 'unshift', 'reverse', 'splice', 'sort'].forEach(method => {
      // 缓存原始方法
      const origin = arrayProto[method];
      // 对可以改变数组的方法进行封装
      // 当使用push方法的时候其实调用的是arrayMethods.push而arrayMethods.push是函数mutator
      // 在mutator函数执行原始的数组方法，我们可以在这个函数中进行一些其他的事情
      Object.defineProperty(arrayMethods, method, {
        value: function mutator(...args) {
          return origin.apply(this, args);
        },
        configurable: true,
        enumerable: true,
        writable: true
      })
    })
  </script>
</body>

</html>